package com.lm.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lm.model.DpChannel;
import com.lm.model.DpTransferLog;
import com.lm.model.LmUser;
import com.lm.model.LmUserBase;
import com.lm.service.*;
import com.lm.utils.ConfigUtil;
import com.meirengu.common.RedisClient;
import com.meirengu.common.StatusCode;
import com.meirengu.controller.BaseController;
import com.meirengu.model.Result;
import com.meirengu.utils.*;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * ${DESCRIPTION}
 *
 * @author Mao
 * @create 2017-05-24 15:58
 */
@Controller
@RequestMapping("receive")
public class ReceiveController extends BaseController {

    private static final Logger logger = LoggerFactory.getLogger(ReceiveController.class);

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private DpChannelService dpChannelService;

    @Autowired
    private DpAreaLimitService dpAreaLimitService;

    @Autowired
    private DpChannelDataService dpChannelDataService;

    @Autowired
    private DpTransferLogService dpTransferLogService;

    @Autowired
    private LmUserBaseService lmUserBaseService;

    @Autowired
    private LmUserService lmUserService;

    @Autowired
    private ReceiveService receiveService;


    /**
     * 推送数据接收
     *
     * @param param
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(method = RequestMethod.POST)
    public Result receive(@RequestBody String param, HttpServletRequest request) {
        String mobile = null;
        String channelNo = null;
        String channelName = null;
        int channelDataId = 0;
        Result result = new Result();
        try {
            logger.debug(param);
            /*密钥*/
            String secret = null;
            /*限制地区*/
            String areaValue = null;
            JSONObject jsonObject = JSON.parseObject(param);
            channelNo = jsonObject.getString("channelNo");
            mobile = jsonObject.getString("mobile");
            String name = jsonObject.getString("name");
            String applyTimeStr = jsonObject.getString("applyTime");
            String sign = jsonObject.getString("sign");
            Integer sex = jsonObject.getIntValue("sex");
            String idCard = jsonObject.getString("idCard");
            Integer areaCode = jsonObject.getInteger("areaCode");
            String areaName = jsonObject.getString("areaName");
            String birthdayStr = jsonObject.getString("birthday");
            BigDecimal expectAmount = jsonObject.getBigDecimal("expectAmount");
            Integer policy = jsonObject.getIntValue("policy");
            Integer credit = jsonObject.getIntValue("credit");
            Integer house = jsonObject.getIntValue("house");
            Integer car = jsonObject.getIntValue("car");
            Integer fund = jsonObject.getIntValue("fund");
            Integer socialSecurity = jsonObject.getIntValue("socialSecurity");
            Integer wxloan = jsonObject.getIntValue("wxloan");
            Integer occupation = jsonObject.getIntValue("occupation");
            Integer workDuration = jsonObject.getIntValue("workDuration");
            Integer salaryMethod = jsonObject.getIntValue("salaryMethod");
            Integer salary = jsonObject.getIntValue("salary");
            String ip = jsonObject.getString("ip");
            /*验证参数是否缺失*/
            if (StringUtils.isBlank(channelNo) || StringUtils.isBlank(mobile) || StringUtils.isBlank(name) ||
                    StringUtils.isBlank(applyTimeStr) || StringUtils.isBlank(sign) || sex == null ||
                    NumberUtil.isNullOrZero(areaCode) || StringUtils.isBlank(areaName) ||
                    StringUtils.isBlank(birthdayStr) || expectAmount == null || policy == null ||
                    credit == null || house == null || car == null || fund == null ||
                    socialSecurity == null || wxloan == null || occupation == null ||
                    workDuration == null || salaryMethod == null || salary == null ||
                    StringUtils.isBlank(ip)) {
                result.setCode(StatusCode.MISSING_ARGUMENT);
                result.setMsg(StatusCode.codeMsgMap.get(StatusCode.MISSING_ARGUMENT));
                return result;
            }
            /*验证是否与原有数据重复*/
            String userExistUrl = ConfigUtil.getConfig("user.exist.url");
            Map<String, String> params = new HashMap<String, String>();
            params.put("mobile", mobile);
            HttpUtil.HttpResult hr = HttpUtil.doPostForm(userExistUrl, params);
            logger.debug("Request: {} getResponse: {}", userExistUrl, hr);
            if (hr.getStatusCode() == HttpStatus.SC_OK) {
                JSONObject resultJson = JSON.parseObject(hr.getContent());
                int code = resultJson.getIntValue("code");
                if (code == StatusCode.USER_IS_EXITS) {
                    result.setCode(StatusCode.USER_IS_EXITS);
                    result.setMsg(StatusCode.codeMsgMap.get(StatusCode.USER_IS_EXITS));
                    return result;
                }
            } else {
                logger.error("httpcode: {}--httpcontent: {}", hr.getStatusCode(), hr.getContent());
                throw new Exception("请求获客服务异常 -- httpCode: " + hr.getStatusCode());
            }

            /*验证渠道的准确性并获取秘钥*/
            DpChannel dpChannel = dpChannelService.detailByChannelNo(channelNo);
            /*无此渠道或渠道已下线*/
            if (dpChannel == null) {
                result.setCode(StatusCode.CHANNEL_REMOVE);
                result.setMsg(StatusCode.codeMsgMap.get(StatusCode.CHANNEL_REMOVE));
                return result;
            } else {
                secret = dpChannel.getSecret();
                areaValue = dpChannel.getAreaValue();
                channelName = dpChannel.getChannelName();
            }
            /*直接查询数据库
            secret = redisClient.get("dpChannelSec"+channelNo);
            channelName = redisClient.get("dpChannelName"+channelNo);
            areaValue = redisClient.get("dpChannelArea"+channelNo);*/
            /*校验手机号格式*/
            if (!ValidatorUtil.isMobile(mobile)) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("手机号码格式错误！");
                return result;
            }
            /*校验姓名格式*/
            if (!ValidatorUtil.isRealName(name)) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("姓名格式错误！");
                return result;
            }

            Date applyTime = null;
            /*校验申请日期格式*/
            if (ValidatorUtil.isDateTime(applyTimeStr)) {
                applyTime = DateUtils.strToDate(applyTimeStr, "yyyy-MM-dd HH:mm:ss");
            } else {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("申请日期格式错误！");
                return result;
            }
            /*校验签名*/
            String signCurrent = MD5Util.MD5(channelNo + name + mobile + secret + applyTimeStr, "UTF-8");
            if (!signCurrent.equals(sign)) {
                result.setCode(StatusCode.SIGN_NOT_MATCH);
                result.setMsg(StatusCode.codeMsgMap.get(StatusCode.SIGN_NOT_MATCH));
                return result;
            }
            if (sex.intValue() < 0 || sex.intValue() > 1) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("性别参数值错误！");
                return result;
            }
            /*验证地区*/
            /*初步验证地区是否限制地区*/
            if (areaValue.contains(areaName)) {
                /*查询channelData表的三个作用*/
                /*1.验证areaCode和areaName是否匹配*/
                /*2.验证地区是否限制地区*/
                /*3.验证该地区当日限量是否已满*/
                Map<String, Object> dpChannelDataParam = new HashMap<>();
                dpChannelDataParam.put("channelNo", channelNo);
                dpChannelDataParam.put("areaCode", areaCode);
                dpChannelDataParam.put("areaName", areaName);
                List<Map<String, Object>> channelDataList = dpChannelDataService.getList(dpChannelDataParam);
                if (channelDataList == null || channelDataList.size() == 0) {
                    result.setCode(StatusCode.AREA_NOT_MATCH);
                    result.setMsg(StatusCode.codeMsgMap.get(StatusCode.AREA_NOT_MATCH));
                    return result;
                } else {
                    Map<String, Object> channelData = channelDataList.get(0);
                    channelDataId = (int) channelData.get("id");
                    int num = (int) channelData.get("num");
                    int receiveNum = (int) channelData.get("receiveNum");
                    if (receiveNum >= num) {
                        result.setCode(StatusCode.AREA_NUM_OUT);
                        result.setMsg(StatusCode.codeMsgMap.get(StatusCode.AREA_NUM_OUT));
                        return result;
                    }
                }
            } else {
                result.setCode(StatusCode.AREA_NOT_MATCH);
                result.setMsg(StatusCode.codeMsgMap.get(StatusCode.AREA_NOT_MATCH));
                return result;
            }
            Date birthday = null;
            /*校验生日日期格式*/
            if (ValidatorUtil.isDateTime(birthdayStr)) {
                birthday = DateUtils.strToDate(birthdayStr, "yyyy-MM-dd");
            } else {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("出生日期格式错误！");
                return result;
            }
            /*借款金额限制*/
            if (expectAmount.intValue() < 20000) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("借款金额错误！");
                return result;
            }
            if (policy.intValue() < 1 || policy.intValue() > 3) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("寿险保单值错误！");
                return result;
            }
            if (credit.intValue() < 1 || credit.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("信用情况值错误！");
                return result;
            }
            if (house.intValue() < 1 || house.intValue() > 3) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("名下房产值错误！");
                return result;
            }
            if (car.intValue() < 1 || car.intValue() > 3) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("名下汽车值错误！");
                return result;
            }
            if (fund.intValue() < 0 || fund.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("公积金值错误！");
                return result;
            }
            if (socialSecurity.intValue() < 0 || socialSecurity.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("社会保险值错误！");
                return result;
            }
            if (wxloan.intValue() < 1 || wxloan.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("微粒贷值错误！");
                return result;
            }
            if (occupation.intValue() < 0 || occupation.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("职业值错误！");
                return result;
            }
            if (workDuration.intValue() < 6 || workDuration.intValue() > 24) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("工作时间值错误！");
                return result;
            }
            if (salaryMethod.intValue() < 1 || salaryMethod.intValue() > 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("工资发放值错误！");
                return result;
            }
            if (salary.intValue() < 1 || salary.intValue() > 5) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("月收入值错误！");
                return result;
            }
            /*暂时去掉ip合法性验证*/
            /*if (!ValidatorUtil.isIPAddr(ip)) {
                return setResult(StatusCode.INVALID_ARGUMENT, null);
            }*/
            /*1.客户贷款需求≥2万 ；
            2.客户年龄应大于等于22周岁且小于等于55周岁；
            3.客户的申请ip地址与客户的手机号一致；
            4.客户至少拥有“银行卡转账，社保，公积金，有房，有车，保单，微粒贷”中一个条件。*/
            int age = DateUtils.getAge(birthday);
            if (age < 22 || age > 55) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("年龄不符合, 22和55之间");
                return result;
            }
            /*验证手机号归属地与用户地址*/
            String mobileUrl = ConfigUtil.getConfig("mobile.url") + "/" + mobile;
            String mobileRegistration = null;
            HttpUtil.HttpResult mobileResult = HttpUtil.doGet(mobileUrl);
            logger.debug("Request: {} getResponse: {}", mobileUrl, mobileResult);
            if (mobileResult.getStatusCode() == HttpStatus.SC_OK) {
                JSONObject resultJson = JSON.parseObject(mobileResult.getContent());
                int code = resultJson.getIntValue("code");
                if (code == StatusCode.OK) {
                    JSONObject productInfo = resultJson.getJSONObject("data");
                    Integer cityCode = productInfo.getIntValue("cityCode");
                    String city = productInfo.getString("city");
                    mobileRegistration = city;
                    if (cityCode != null && cityCode.intValue() != areaCode.intValue()) {
                        result.setCode(StatusCode.INVALID_ARGUMENT);
                        result.setMsg("手机号码归属地和城市不匹配！");
                        return result;
                    }
                } else {
                    logger.error("businesscode: {}--msg: {}", code, StatusCode.codeMsgMap.get(code));
                    throw new Exception("请求资讯服务异常 -- StatusCode: " + code);
                }
            } else {
                logger.error("httpcode: {}--httpcontent: {}", mobileResult.getStatusCode(), mobileResult.getContent());
                throw new Exception("请求资讯服务异常 -- httpCode: " + mobileResult.getStatusCode());
            }
            /*验证7其一*/
            if (salaryMethod.intValue() == 2 && socialSecurity.intValue() == 0 && fund.intValue() == 0 &&
                    house.intValue() == 1 && car.intValue() == 1 && policy.intValue() == 1 && wxloan.intValue() == 2) {
                result.setCode(StatusCode.INVALID_ARGUMENT);
                result.setMsg("数据条件不符合！");
                return result;
            }
            /*入库*/
            /*保存贷款用户资质信息*/
            LmUser lmUser = new LmUser();
            lmUser.setName(name);
            lmUser.setPhone(mobile);
            lmUser.setSex(sex);
            lmUser.setBirthday(birthday);
            lmUser.setAge(age);
            lmUser.setAreaCode(areaCode);
            lmUser.setAreaName(areaName);
            lmUser.setIp(ip);
            lmUser.setIdCard(idCard);
            lmUser.setExpectAmount(expectAmount.doubleValue());
            lmUser.setPolicy(policy);
            lmUser.setCredit(credit);
            lmUser.setHouse(house);
            lmUser.setCar(car);
            lmUser.setFund(fund);
            lmUser.setSocialSecurity(socialSecurity);
            lmUser.setOccupation(occupation);
            lmUser.setSalaryMethod(salaryMethod);
            lmUser.setWorkDuration(workDuration);
            lmUser.setSalary(salary);
            lmUser.setWxloan(wxloan);
            lmUser.setSubmitStage(2);
            lmUserService.insert(lmUser);
            /*保存客户渠道信息*/
            LmUserBase lmUserBase = new LmUserBase();
            lmUserBase.setRegisterFrom(3);//推送渠道
            lmUserBase.setChannelId(dpChannel.getId());
            lmUserBase.setChannelCode(channelNo);
            lmUserBase.setChannelName(channelName);
            lmUserBase.setName(name);
            lmUserBase.setPhone(mobile);
            lmUserBase.setUserId(lmUser.getId());
            lmUserBaseService.insert(lmUserBase);
            /*更新推送数据表*/
            dpChannelDataService.updateReceiveNum(channelDataId);
            //通过消息队列发到秒单之家
            JSONObject userInfoJson = (JSONObject) JSON.toJSON(lmUser);
            userInfoJson.put("registerFrom", lmUserBase.getRegisterFrom());
            userInfoJson.put("channelId", dpChannel.getId());
            userInfoJson.put("channelCode", channelNo);
            userInfoJson.put("channelName", channelName);
            userInfoJson.put("mobile", mobile);
            userInfoJson.put("mobileRegistration", mobileRegistration);
            receiveService.sendMDZJ(userInfoJson, lmUser.getId());
            result.setCode(StatusCode.OK);
            result.setMsg(StatusCode.codeMsgMap.get(StatusCode.OK));
            return result;

        } catch (Exception e) {
            e.printStackTrace();
            String params = String.format("参数:param:%s", param);
            logger.error("ReceiveController receive throws Exceprion :{} happens. params:{}.", ExceptionUtils.getFullStackTrace(e), params);
            result.setCode(StatusCode.INTERNAL_SERVER_ERROR);
            result.setMsg(StatusCode.codeMsgMap.get(StatusCode.INTERNAL_SERVER_ERROR));
            return result;
        } finally {
            DpTransferLog dpTransferLog = new DpTransferLog();
            dpTransferLog.setChannelNo(channelNo);
            dpTransferLog.setChannelName(channelName);
            dpTransferLog.setMobile(mobile);
            dpTransferLog.setContent(param);
            dpTransferLog.setCode(result.getCode());
            dpTransferLog.setMessage(result.getMsg());
            dpTransferLog.setIp(RequestUtil.getClientIp(request));
            dpTransferLogService.insert(dpTransferLog);
        }


    }

}
